
// INCLUDES ********************************************************************

#include "Texture2D.h"

#include "TexturedPolygon.h"

#include "Triangulator.h"

#include "TextureCache.h"

// GLOBALS *********************************************************************

// NAMESPACES ******************************************************************

#pragma mark -
#pragma mark Constructor
// -----------------------------------------------------------------------------

Meteor::TexturedPolygon::TexturedPolygon( const std::string& textureFileName, 
                                          const std::vector<Meteor::Vector2D>& shapeVertices)

: mShapeVertices( shapeVertices), mTextureVertices(), mTriangulatedVertices(),
  mHasStroke( false), mStrokeColor( 0.0f, 0.0f, 0.0f, 1.0f)
{
    Initialize( textureFileName);
    
    CalculateVertices( shapeVertices); 
    
    mShape = shapeVertices;
    
    //! stroke needs to go back to the first vertex
    mShape.push_back( mShape[0]);
}


#pragma mark -
#pragma mark Destructor
// -----------------------------------------------------------------------------

Meteor::TexturedPolygon::~TexturedPolygon()
{
}


#pragma mark -
#pragma mark Initialization
// -----------------------------------------------------------------------------

void Meteor::TexturedPolygon::Initialize( const std::string& fileName)
{
    mTexture = TextureCache::Instance().AddObject( fileName);
    
    if ( mTexture == nullptr)
    {
        Logger::DebugLog( "Sprite::Initialize - error creating texture");
        
        return;
    }
    
    SetSize( mTexture->Width(), mTexture->Height());
    
    //! we want repitition of our texture all over
    mTexture->SetParameter( GL_TEXTURE_WRAP_S, GL_REPEAT);
    
    mTexture->SetParameter( GL_TEXTURE_WRAP_T, GL_REPEAT);
}

#pragma mark -
#pragma mark Calculations
// -----------------------------------------------------------------------------

void Meteor::TexturedPolygon::CalculateVertices( const std::vector<Meteor::Vector2D>& shapeVertices)
{
    Triangulator::Process( shapeVertices, mTriangulatedVertices);
    
    const float textureWidthRatio = 1.0f / mTexture->Width();

    for ( int i = 0; i < mTriangulatedVertices.size(); i++)
    {
        mTextureVertices.push_back( mTriangulatedVertices[i] * textureWidthRatio);
    }
}

#pragma mark -
#pragma mark Update/draw cycles
// -----------------------------------------------------------------------------

void Meteor::TexturedPolygon::SetStroke( const Meteor::Color& color, const float width)
{
    mHasStroke = true;
    
    mStrokeWidth = width;
    
    mStrokeColor = color;
}


#pragma mark -
#pragma mark Update/draw cycles
// -----------------------------------------------------------------------------

void Meteor::TexturedPolygon::Update( const float deltaTime)
{
}

// -----------------------------------------------------------------------------

void Meteor::TexturedPolygon::Draw() const
{   
    if ( mTexture == nullptr)
    {
        return;
    }
    
    glPushMatrix();

    glBindTexture( GL_TEXTURE_2D, mTexture->Name());
    
    glEnable( GL_TEXTURE_2D);
    
    glEnableClientState( GL_VERTEX_ARRAY);
    
    glEnableClientState( GL_TEXTURE_COORD_ARRAY);
    
    glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
    
    glVertexPointer( 2, GL_FLOAT, 0, &mTriangulatedVertices[0]);
    
    glTexCoordPointer( 2, GL_FLOAT, 0, &mTextureVertices[0]);
    
    Drawable::Draw();
    
    glDrawArrays( GL_TRIANGLE_STRIP, 0, mTriangulatedVertices.size());
    
    glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    
    glDisableClientState( GL_TEXTURE_COORD_ARRAY);
    
    glDisableClientState( GL_COLOR_ARRAY);
    
    glDisable( GL_TEXTURE_2D);
        
    if ( mHasStroke == true)
    {
        glLineWidth( mStrokeWidth);
        
        glColor4f( mStrokeColor.Red(), mStrokeColor.Green(), mStrokeColor.Blue(), mStrokeColor.Alpha());
        
        glVertexPointer( 2, GL_FLOAT, 0, &mShape[0]);
    
        glDrawArrays( GL_LINE_STRIP, 0, mShape.size());
    }
    
    glPopMatrix();
}
